context
我在开发中遇到一个问题, 就是传统的Target-Action
没法满足我的要求. 因为当按钮触发的瞬间, 控制器可能已经被销毁了. Target
没有了. 暂且不说这个设计的优劣, 单纯从技术方面,剖析一下是否可以实现一个按钮 ,这个按钮不依赖外部 Target
,而是依赖自己.
几个想法
首先想到的是继承UIButton
,然后给Button
增加一个block
属性 ,然后内部执行block
代码.
但是这样要求我项目中所有使用UIButton的地方都需要修改 ,成本太高,遂放弃.
然后想到通过给UIButton
添加Category
的方式,完成需求. 之前曾经做个一个分类,就是让NSObject
携带一个字典,字典内部可以带上用户自定义的一些参数.解决了一些seletor
不能传递任意参数的问题. 所以,这次给Button
分类增加个属性,也没有什么问题:
1 | #import <UIKit/UIKit.h> |
定义了一个没有返回值的block
作为参数, 然后暴露一个方法供外部调用.
然后 .m 文件
1 | static char identifier = 'g'; |
利用Runtime
动态给对象(self)添加一个codeBlock
,使用的内存管理机制(关联策略)是OBJC_ASSOCIATION_COPY_NONATOMIC
.
关于关联策略,有以下几种:
1 | OBJC_ASSOCIATION_ASSIGN @property (assign) or @property (unsafe_unretained) 弱引用关联对象 |
有开发经验的人都明白其中的意思,在此不再赘述.
然后, 给自己添加了一个Target-Action
1 | [self addTarget:self action:@selector(callActionCodeBlock:) forControlEvents:event]; |
最后,实现 selector
,代码如下:
1 | - (void)callActionCodeBlock:(id)sender { |
通过 objc_getAssociatedObject
拿到self中的 identifier为g
的对象(block),然后如果block存在,则执行.